﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MindFusion.Diagramming;
using System.Xml.Serialization;
using System.IO;

namespace WindowsFormsApplication1
{
    public enum Mode { Create, Modify };

    public partial class Form1 : Form
    {
        FormChangeName fcn = new FormChangeName();
        Mode mode;
        bool diagramSaved = true;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            diagramView.Behavior = Behavior.DrawLinks;
            diagram.DefaultShape = Shapes.Ellipse;
            diagram.DrawNode += new DrawNodeEventHandler(diagram1_DrawNode);
            diagram.LinkCreated += new LinkEventHandler(diagram1_LinkCreated);
            diagramView.MouseWheel += new MouseEventHandler(diagramView_MouseWheel);
            diagram.UndoManager.UndoEnabled = true;

            cmbLinkType.SelectedIndex = 0;
            cmbNodeType.SelectedIndex = 0;
        }

        void diagramView_MouseWheel(object sender, MouseEventArgs e)
        {
            if (e.Delta > 0) diagramView.ZoomIn();
            else if (e.Delta < 0) diagramView.ZoomOut();
        }

        void diagram1_LinkCreated(object sender, LinkEventArgs e)
        {
            e.Link.Text = cmbLinkType.Text;
            Validation();
        }

        void diagram1_DrawNode(object sender, DrawNodeEventArgs e)
        {
            System.Drawing.Drawing2D.GraphicsPath x =
               new System.Drawing.Drawing2D.GraphicsPath();

            x.AddEllipse(e.Bounds);

            Color surrounding;
            if (e.Node.Tag.ToString() == "named") surrounding = Color.Blue;
            else surrounding = Color.Green;

            System.Drawing.Drawing2D.PathGradientBrush p =
               new System.Drawing.Drawing2D.PathGradientBrush(x);
            p.CenterColor = Color.White;
            p.SurroundColors = new Color[] { surrounding };

            e.Graphics.FillEllipse(p, e.Bounds);
            string s = (e.Node as ShapeNode).Text;
            e.Graphics.DrawString(s, Font, Brushes.Black, PointF.Add(e.Node.GetCenter(), new SizeF((float)(-3.5 * s.Length), 10)));

            p.Dispose();
            x.Dispose();

            System.Drawing.Pen pp = new System.Drawing.Pen(surrounding, 0);

            e.Graphics.DrawEllipse(pp, e.Bounds);

            pp.Dispose();
        }

        PointF pt = new PointF(-50, -50);
        SizeF sz10 = new SizeF(10, 10);
        SizeF sz20 = new SizeF(20, 20);
        bool showChangeNameForm = true;

        private void diagramView1_MouseUp(object sender, MouseEventArgs e)
        {
            if (pt.X == e.X && pt.Y == e.Y)
            {
                pt.X -= 10;
                pt.Y -= 10;
                MindFusion.Diagramming.ShapeNode node = diagram.Factory.CreateShapeNode(pt, sz20);
                if (cmbNodeType.SelectedIndex == 0)
                    node.Tag = "unnamed";
                else
                    node.Tag = "named";
                if (node.Tag.ToString() == "named") node.Text = "Node" + diagram.Nodes.Count.ToString();
                node.CustomDraw = CustomDraw.Full;
                node.Brush = new MindFusion.Drawing.LinearGradientBrush(Color.White, Color.Green);
                node.Constraints.MaxHeight = node.Constraints.MinHeight = 20;
                node.Constraints.MaxWidth = node.Constraints.MinWidth = 20;
                diagramSaved = false;
                ShowNameTextbox(node);
            }
        }

        void ShowNameTextbox(ShapeNode node)
        {
            if (node.Tag.ToString() == "named")
            {
                txtName = new TextBox();
                this.Controls.Add(txtName);
                txtName.TextAlign = HorizontalAlignment.Center;
                txtName.Location = Point.Add(Point.Ceiling(node.GetCenter() + (new SizeF(-txtName.Width / 2, 10))), new Size(diagramView.Location));
                txtName.Text = node.Text;
                txtName.SelectAll();
                txtName.KeyDown += new KeyEventHandler(txtName_KeyDown);
                txtName.LostFocus += new EventHandler(txtName_LostFocus);
                txtName.BringToFront();
                txtName.Show();
                txtName.Focus();
            }
        }

        void txtName_LostFocus(object sender, EventArgs e)
        {
            (sender as TextBox).Dispose();
        }

        void txtName_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                (diagram.Selection.Nodes[0] as ShapeNode).Text = (sender as TextBox).Text;
                (sender as TextBox).Dispose();
            }
            else if (e.KeyCode == Keys.Escape)
                (sender as TextBox).Dispose();
        }

        private void diagramView1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if (/*diagram.Selection.Items.Count==0 && */diagram.GetNodeAt(e.Location, 20) == null && diagram.GetLinkAt(e.Location, 20) == null)
                    pt = e.Location;
                else
                {
                    pt.X = -50;
                    pt.Y = -50;
                }
            }
            else if (e.Button == MouseButtons.Right)
            {
                diagramView.ContextMenuStrip = null;
                contextMenuNode.Items[0].Enabled = false;
                if (diagram.GetNodeAt(e.Location, 20) != null)
                {
                    if (diagram.GetNodeAt(e.Location, 20).Tag.ToString() == "named") contextMenuNode.Items[0].Enabled = true;
                    diagramView.ContextMenuStrip = contextMenuNode;
                    diagram.Selection.Clear();
                    diagram.GetNodeAt(e.Location, 20).Selected = true;
                }
                else if (diagram.GetLinkAt(e.Location, 20) != null)
                {
                    diagramView.ContextMenuStrip = contextMenuLink;
                    diagram.Selection.Clear();
                    diagram.GetLinkAt(e.Location, 20).Selected = true;
                }
            }
        }

        bool Validation()
        {
            DiagramLink linkToDelete = null;
            foreach (DiagramLink link in diagram.Links)
            {
                if (link.Text == "name" && link.Destination.Tag.ToString() == "unnamed")
                {
                    MessageBox.Show("Дуга типа 'name' может входить только в именованную вершину");
                    linkToDelete = link;
                }
                if (link.Origin.Tag.ToString() == "named")
                {
                    MessageBox.Show("Из именованной вершины не может выходить дуг");
                    linkToDelete = link;
                }
                if (link.Destination.Tag.ToString() == "named" && link.Text != "name")
                {
                    MessageBox.Show("В именованную вершину может входить только дуга типа 'name'");
                    linkToDelete = link;
                }
            }
            if (linkToDelete != null)
            {
                diagram.Links.Remove(linkToDelete);
                return false;
            }
            return true;
        }

        private void diagramView_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Control && e.KeyCode == Keys.Z) diagram.UndoManager.Undo();
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            if (saveFileDialog.ShowDialog() == DialogResult.OK)
            {
                Semantic.SemanticNetwork sn = Converter.Diagram2SemanticNet(diagram);
                XmlSerializer xs = new XmlSerializer(typeof(Semantic.SemanticNetwork));
                xs.Serialize(new StreamWriter(saveFileDialog.FileName), sn);
                diagram.SaveToXml(saveFileDialog.FileName + ".diagram");
                diagramSaved = true;
            }
        }

        private void btnLoad_Click(object sender, EventArgs e)
        {
            if (!diagramSaved)
            {
                DialogResult dr = MessageBox.Show("Текущая диаграмма не сохранена! Хотите ее сохранить?", "", MessageBoxButtons.YesNoCancel);
                if (dr == DialogResult.Yes) btnSave_Click(sender, e);
                if (dr == DialogResult.Cancel) return;
            }
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                Semantic.SemanticNetwork sn;
                XmlSerializer xs = new XmlSerializer(typeof(Semantic.SemanticNetwork));
                sn = xs.Deserialize(new StreamReader(openFileDialog.FileName)) as Semantic.SemanticNetwork;
                diagram.LoadFromXml(openFileDialog.FileName + ".diagram");
                diagramSaved = true;
            }
        }

        private void btnNew_Click(object sender, EventArgs e)
        {
            if (!diagramSaved)
            {
                DialogResult dr = MessageBox.Show("Текущая диаграмма не сохранена! Хотите ее сохранить?", "", MessageBoxButtons.YesNoCancel);
                if (dr == DialogResult.Yes) btnSave_Click(sender, e);
                if (dr == DialogResult.Cancel) return;
            }
            diagram.ClearAll();
            diagramView.Refresh();
        }

        private void diagram_LinkSelected(object sender, LinkEventArgs e)
        {
            e.Link.Pen.Width = 3;
        }

        private void diagram_LinkDeselected(object sender, LinkEventArgs e)
        {
            e.Link.Pen.Width = 1;
        }

        TextBox txtName;

        private void diagram_NodeSelected(object sender, NodeEventArgs e)
        {
            //if (e.Node.Tag.ToString() == "named" && diagramView.ContextMenuStrip == null)
            //{
            //    fcn = new FormChangeName();
            //    fcn.Location = Point.Add(MousePosition, sz10.ToSize());
            //    fcn.Owner = this;
            //    fcn.Show();
            //    fcn.txtName.Text = (e.Node as ShapeNode).Text; 
            //    this.Activate();
            //}

        }

        private void diagram_NodeDeselected(object sender, NodeEventArgs e)
        {
            //if (fcn != null)
            //{
            //    fcn.Close(); 
            //}
        }

        private void diagram_LinkModified(object sender, LinkEventArgs e)
        {
            diagramSaved = false;
        }

        private void diagram_NodeModified(object sender, NodeEventArgs e)
        {
            diagramSaved = false;
        }

        private void удалитьToolStripMenuItem_Click(object sender, EventArgs e)
        {
            diagram.Nodes.Remove(diagram.Selection.Nodes[0]);
        }

        private void удалитьToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            diagram.Links.Remove(diagram.Selection.Links[0]);
        }

        private void сменитьИмяToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DiagramNode node = diagram.Selection.Nodes[0];
            if (node != null) ShowNameTextbox(node as ShapeNode);
        }
    }
}
